﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;


namespace SimpleRedisClinet
{
    /// <summary>
    /// simple redis client class
    /// yangmeng(hvbird@gmail.com)
    /// 2011-01-21
    /// </summary>
    public class RedisSortedSet : RedisBase
    {
        public RedisSortedSet(string hostip, int port)
            : base(hostip,port)
        {
            
        }

        public bool AddMember<T>(string key, int score, T obj)
        {
            check_key(key);

            System.Text.StringBuilder sb = new StringBuilder();
            sb.Append("ZADD ");
            sb.Append(key);
            sb.Append(" ");
            sb.Append(score + " ");

            string strvalue = get_serializer_str<T>(obj);
            sb.Append(System.Text.Encoding.UTF8.GetByteCount(strvalue));
            sb.Append("\r\n");
            sb.Append(strvalue);
            sb.Append("\r\n");


            ResponseClass ret = send_and_receive(sb.ToString());

            if (ret.Number > 0)
                return true;

            return false;
        }

        public bool RemoveMember<T>(string key, T obj)
        {
            // not exists or data type error
            if (GetDataType(key) != RedisDataType.ZSet)
                return false;

            System.Text.StringBuilder sb = new StringBuilder();
            sb.Append("ZREM " + key + " ");

            string strvalue = get_serializer_str<T>(obj);
            sb.Append(System.Text.Encoding.UTF8.GetByteCount(strvalue));
            sb.Append("\r\n");
            sb.Append(strvalue);
            sb.Append("\r\n");

            ResponseClass ret = send_and_receive(sb.ToString());

            if (ret.Number > 0)
                return true;

            return false;
        }

        public int GetRankAsc<T>(string key, T obj)
        {
            check_key(key);

            // not exists or data type error
            if (GetDataType(key) != RedisDataType.ZSet)
                return 0;

            System.Text.StringBuilder sb = new StringBuilder();
            sb.Append("ZRANK " + key + " ");

            string strvalue = get_serializer_str<T>(obj);
            sb.Append(System.Text.Encoding.UTF8.GetByteCount(strvalue));
            sb.Append("\r\n");
            sb.Append(strvalue);
            sb.Append("\r\n");

            ResponseClass ret = send_and_receive(sb.ToString());

            return ret.Number;
        }

        public int GetRankDesc<T>(string key, T obj)
        {
            check_key(key);

            // not exists or data type error
            if (GetDataType(key) != RedisDataType.ZSet)
                return 0;

            System.Text.StringBuilder sb = new StringBuilder();
            sb.Append("ZREVRANK " + key + " ");

            string strvalue = get_serializer_str<T>(obj);
            sb.Append(System.Text.Encoding.UTF8.GetByteCount(strvalue));
            sb.Append("\r\n");
            sb.Append(strvalue);
            sb.Append("\r\n");

            ResponseClass ret = send_and_receive(sb.ToString());

            return ret.Number;
        }

        public int GetScore<T>(string key, T obj)
        {
            check_key(key);

            // not exists or data type error
            if (GetDataType(key) != RedisDataType.ZSet)
                return 0;

            System.Text.StringBuilder sb = new StringBuilder();
            sb.Append("ZSCORE " + key + " ");

            string strvalue = get_serializer_str<T>(obj);
            sb.Append(System.Text.Encoding.UTF8.GetByteCount(strvalue));
            sb.Append("\r\n");
            sb.Append(strvalue);
            sb.Append("\r\n");

            ResponseClass ret = send_and_receive(sb.ToString());

            return ret.Number;
        }

        public int GetItemCount(string key)
        {
            check_key(key);

            // not exists or data type error
            if (GetDataType(key) != RedisDataType.ZSet)
                return 0;

            string cmdstr = "ZCARD " + key + "\r\n";

            ResponseClass ret = send_and_receive(cmdstr);

            return ret.Number;
        }

        public List<T> GetRageItemsAsc<T>(string key, int start, int end)
        {
            List<T> retlist = new List<T>();

            // not exists or data type error
            if (GetDataType(key) != RedisDataType.ZSet)
                return retlist;

            string cmdstr = "ZRANGE " + key + " " + start + " " + end + "\r\n";

            ResponseClass ret = send_and_receive(cmdstr);

            for (int i = 0; i < ret.Strings.Count; i++)
            {
                T retobj = get_deserialized_obj<T>(ret.Strings[i]);
                retlist.Add(retobj);
            }

            return retlist;
        }

        public List<T> GetRageItemsDesc<T>(string key, int start, int end)
        {
            List<T> retlist = new List<T>();

            // not exists or data type error
            if (GetDataType(key) != RedisDataType.ZSet)
                return retlist;

            string cmdstr = "ZREVRANGE " + key + " " + start + " " + end + "\r\n";

            ResponseClass ret = send_and_receive(cmdstr);

            for (int i = 0; i < ret.Strings.Count; i++)
            {
                T retobj = get_deserialized_obj<T>(ret.Strings[i]);

                retlist.Add(retobj);
            }

            return retlist;
        }
    }
}
